﻿/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file            : usb_host.c
  * @version         : v1.0_Cube
  * @brief           : This file implements the USB Host
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/

#include "usb_host.h"
#include "usbh_core.h"
#include "usbh_hid.h"
#include "usbh_hid_keybd.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN 1 */


// 处理键盘数据函数
void ProcessKeyboardData(HID_KEYBD_Info_TypeDef *info)
{
  static HID_KEYBD_Info_TypeDef prev_info = {0};
  
  // 检查数据是否有变化
  uint8_t data_changed = 0;
  if (info->lctrl != prev_info.lctrl ||
      info->lshift != prev_info.lshift ||
      info->lalt != prev_info.lalt ||
      info->lgui != prev_info.lgui ||
      info->rctrl != prev_info.rctrl ||
      info->rshift != prev_info.rshift ||
      info->ralt != prev_info.ralt ||
      info->rgui != prev_info.rgui) {
    data_changed = 1;
  } else {
    for (int i = 0; i < 6; i++) {
      if (info->keys[i] != prev_info.keys[i]) {
        data_changed = 1;
        break;
      }
    }
  }
  
  if (!data_changed) {
    return;  // 数据没有变化，不处理
  }
  
  // 保存当前数据
  prev_info = *info;
  
  // 打印修饰键状态
  printf("Modifiers: ");
  if (info->lctrl) printf("LeftCtrl ");
  if (info->lshift) printf("LeftShift ");
  if (info->lalt) printf("LeftAlt ");
  if (info->lgui) printf("LeftGUI ");
  if (info->rctrl) printf("RightCtrl ");
  if (info->rshift) printf("RightShift ");
  if (info->ralt) printf("RightAlt ");
  if (info->rgui) printf("RightGUI ");
  if (!(info->lctrl || info->lshift || info->lalt || info->lgui || 
        info->rctrl || info->rshift || info->ralt || info->rgui)) {
    printf("None ");
  }
  printf("\r\n");
  
  // 检查按下的普通键
  for (int i = 0; i < 6; i++) {
    if (info->keys[i] != 0) {
      printf("Key pressed: 0x%02X", info->keys[i]);
      
      // 尝试获取ASCII码
      uint8_t ascii_code = USBH_HID_GetASCIICode(info);
      if (ascii_code != 0) {
        printf(" ('%c')", ascii_code);
      }
      
      // 按键映射
      switch (info->keys[i]) {
        case 0x04: printf(" -> A"); break;
        case 0x05: printf(" -> B"); break;
        case 0x06: printf(" -> C"); break;
        case 0x07: printf(" -> D"); break;
        case 0x08: printf(" -> E"); break;
        case 0x09: printf(" -> F"); break;
        case 0x0A: printf(" -> G"); break;
        case 0x0B: printf(" -> H"); break;
        case 0x0C: printf(" -> I"); break;
        case 0x0D: printf(" -> J"); break;
        case 0x0E: printf(" -> K"); break;
        case 0x0F: printf(" -> L"); break;
        case 0x10: printf(" -> M"); break;
        case 0x11: printf(" -> N"); break;
        case 0x12: printf(" -> O"); break;
        case 0x13: printf(" -> P"); break;
        case 0x14: printf(" -> Q"); break;
        case 0x15: printf(" -> R"); break;
        case 0x16: printf(" -> S"); break;
        case 0x17: printf(" -> T"); break;
        case 0x18: printf(" -> U"); break;
        case 0x19: printf(" -> V"); break;
        case 0x1A: printf(" -> W"); break;
        case 0x1B: printf(" -> X"); break;
        case 0x1C: printf(" -> Y"); break;
        case 0x1D: printf(" -> Z"); break;
        case 0x1E: printf(" -> 1"); break;
        case 0x1F: printf(" -> 2"); break;
        case 0x20: printf(" -> 3"); break;
        case 0x21: printf(" -> 4"); break;
        case 0x22: printf(" -> 5"); break;
        case 0x23: printf(" -> 6"); break;
        case 0x24: printf(" -> 7"); break;
        case 0x25: printf(" -> 8"); break;
        case 0x26: printf(" -> 9"); break;
        case 0x27: printf(" -> 0"); break;
        case 0x28: printf(" -> Enter"); break;
        case 0x29: printf(" -> Escape"); break;
        case 0x2A: printf(" -> Backspace"); break;
        case 0x2B: printf(" -> Tab"); break;
        case 0x2C: printf(" -> Space"); break;
        case 0x2D: printf(" -> -"); break;
        case 0x2E: printf(" -> ="); break;
        case 0x2F: printf(" -> ["); break;
        case 0x30: printf(" -> ]"); break;
        case 0x31: printf(" -> \\"); break;
        case 0x33: printf(" -> ;"); break;
        case 0x34: printf(" -> '"); break;
        case 0x35: printf(" -> `"); break;
        case 0x36: printf(" -> ,"); break;
        case 0x37: printf(" -> ."); break;
        case 0x38: printf(" -> /"); break;
        case 0x39: printf(" -> Caps Lock"); break;
        case 0x3A: printf(" -> F1"); break;
        case 0x3B: printf(" -> F2"); break;
        case 0x3C: printf(" -> F3"); break;
        case 0x3D: printf(" -> F4"); break;
        case 0x3E: printf(" -> F5"); break;
        case 0x3F: printf(" -> F6"); break;
        case 0x40: printf(" -> F7"); break;
        case 0x41: printf(" -> F8"); break;
        case 0x42: printf(" -> F9"); break;
        case 0x43: printf(" -> F10"); break;
        case 0x44: printf(" -> F11"); break;
        case 0x45: printf(" -> F12"); break;
        case 0x46: printf(" -> Print Screen"); break;
        case 0x47: printf(" -> Scroll Lock"); break;
        case 0x48: printf(" -> Pause"); break;
        case 0x49: printf(" -> Insert"); break;
        case 0x4A: printf(" -> Home"); break;
        case 0x4B: printf(" -> Page Up"); break;
        case 0x4C: printf(" -> Delete"); break;
        case 0x4D: printf(" -> End"); break;
        case 0x4E: printf(" -> Page Down"); break;
        case 0x4F: printf(" -> Right Arrow"); break;
        case 0x50: printf(" -> Left Arrow"); break;
        case 0x51: printf(" -> Down Arrow"); break;
        case 0x52: printf(" -> Up Arrow"); break;
        case 0x53: printf(" -> Num Lock"); break;
        case 0x54: printf(" -> Keypad /"); break;
        case 0x55: printf(" -> Keypad *"); break;
        case 0x56: printf(" -> Keypad -"); break;
        case 0x57: printf(" -> Keypad +"); break;
        case 0x58: printf(" -> Keypad Enter"); break;
        case 0x59: printf(" -> Keypad 1"); break;
        case 0x5A: printf(" -> Keypad 2"); break;
        case 0x5B: printf(" -> Keypad 3"); break;
        case 0x5C: printf(" -> Keypad 4"); break;
        case 0x5D: printf(" -> Keypad 5"); break;
        case 0x5E: printf(" -> Keypad 6"); break;
        case 0x5F: printf(" -> Keypad 7"); break;
        case 0x60: printf(" -> Keypad 8"); break;
        case 0x61: printf(" -> Keypad 9"); break;
        case 0x62: printf(" -> Keypad 0"); break;
        case 0x63: printf(" -> Keypad ."); break;
        // 可以继续添加更多按键映射...
        default: printf(" -> Unknown key"); break;
      }
      printf("\r\n");
    }
  }
}

// HID应用程序处理
static void HID_Application(USBH_HandleTypeDef *phost)
{
  // 获取键盘信息
  HID_KEYBD_Info_TypeDef *keybd_info = USBH_HID_GetKeybdInfo(phost);
  
  if (keybd_info != NULL) {
    // 处理键盘数据
    ProcessKeyboardData(keybd_info);
  }
}

/* USER CODE END 1 */
/* USER CODE END PFP */

/* USB Host core handle declaration */
USBH_HandleTypeDef hUsbHostFS;
ApplicationTypeDef Appli_state = APPLICATION_IDLE;

/*
 * -- Insert your variables declaration here --
 */
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/*
 * user callback declaration
 */
static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id);

/*
 * -- Insert your external function declaration here --
 */
/* USER CODE BEGIN 1 */
// HID事件回调函数
void USBH_HID_EventCallback(USBH_HandleTypeDef *phost)
{
  if (USBH_HID_GetDeviceType(phost) == HID_KEYBOARD) {
    HID_Application(phost);
  }
}
/* USER CODE END 1 */

/**
  * Init USB host library, add supported class and start the library
  * @retval None
  */
void MX_USB_HOST_Init(void)
{
  /* USER CODE BEGIN USB_HOST_Init_PreTreatment */

  /* USER CODE END USB_HOST_Init_PreTreatment */

  /* Init host Library, add supported class and start the library. */
  if (USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS) != USBH_OK)
  {
    Error_Handler();
  }
  if (USBH_RegisterClass(&hUsbHostFS, USBH_HID_CLASS) != USBH_OK)
  {
    Error_Handler();
  }
  if (USBH_Start(&hUsbHostFS) != USBH_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USB_HOST_Init_PostTreatment */

  /* USER CODE END USB_HOST_Init_PostTreatment */
}

/*
 * Background task
 */
void MX_USB_HOST_Process(void)
{
  /* USB Host Background task */
  USBH_Process(&hUsbHostFS);
}
/*
 * user callback definition
 */


static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id)
{
  /* USER CODE BEGIN CALL_BACK_1 */
  switch(id)
  {
  case HOST_USER_SELECT_CONFIGURATION:
    break;

  case HOST_USER_DISCONNECTION:
    Appli_state = APPLICATION_DISCONNECT;
    printf("USB Device Disconnected\r\n");
    break;

  case HOST_USER_CLASS_ACTIVE:
    Appli_state = APPLICATION_READY;
    printf("USB Keyboard Ready\r\n");
    break;

  case HOST_USER_CONNECTION:
    Appli_state = APPLICATION_START;
    printf("USB Device Connected\r\n");
    break;

  default:
    break;
  }
  /* USER CODE END CALL_BACK_1 */
}

/**
  * @}
  */

/**
  * @}
  */